home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UUPC11QS.ARJ / DCPXFER.C < prev    next >
C/C++ Source or Header  |  1991-11-16  |  42KB  |  1,110 lines

  1. /*
  2.    For best results in visual layout while viewing this file, set
  3.    tab stops to every 4 columns.
  4.    "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987
  5. */
  6.  
  7. /*
  8.    dcpxfer.c
  9.  
  10.    Revised edition of dcp
  11.  
  12.    Stuart Lynne May/87
  13.  
  14.    Copyright (c) Richard H. Lamb 1985, 1986, 1987
  15.    Changes Copyright (c) Stuart Lynne 1987
  16.    Changes Copyright (c) Jordan Brown 1990, 1991
  17.    Changes Copyright (c) Andrew H. Derbyshire 1989, 1991
  18.  
  19.  
  20.    Maintenance Notes:
  21.  
  22.    01Nov87 - that strncpy should be a memcpy! - Jal
  23.    22Jul90 - Add check for existence of the file before writing
  24.              it.                                                  ahd
  25.    09Apr91 - Add numerous changes from H.A.E.Broomhall and Cliff
  26.              Stanford for bidirectional support                   ahd
  27.    05Jul91 - Merged various changes from Jordan Brown's (HJB)
  28.              version of UUPC/extended to clean up transmission
  29.              of commands, etc.                                    ahd
  30.    09Jul91 - Rewrite to use unique routines for all four kinds of
  31.              transfers to allow for testing and security          ahd
  32.  
  33. */
  34.  
  35.  
  36. /*--------------------------------------------------------------------*/
  37. /*                        System include files                        */
  38. /*--------------------------------------------------------------------*/
  39.  
  40. #include <ctype.h>
  41. #include <fcntl.h>
  42. #include <direct.h>
  43. #include <io.h>
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. #include <time.h>
  48. #include <sys/types.h>
  49. #include <sys/stat.h>
  50. #include <sys/timeb.h>
  51.  
  52. /*--------------------------------------------------------------------*/
  53. /*                    UUPC/extended include files                     */
  54. /*--------------------------------------------------------------------*/
  55.  
  56. #include "lib.h"
  57. #include "dcp.h"
  58. #include "dcpsys.h"
  59. #include "dcpxfer.h"
  60. #include "expath.h"
  61. #include "hlib.h"
  62. #include "hostable.h"
  63. #include "import.h"
  64. #include "security.h"
  65. #include "ulib.h"
  66.  
  67. /*--------------------------------------------------------------------*/
  68. /*                          Global variables                          */
  69. /*--------------------------------------------------------------------*/
  70.  
  71. static unsigned char rpacket[MAXPACK], spacket[MAXPACK];
  72.  
  73. static int S_size;   /* number of bytes in the spacket buffer */
  74.  
  75. static char fname[FILENAME_MAX], tname[FILENAME_MAX], dname[FILENAME_MAX];
  76. static char type, who[20], cmdopts[16];
  77.  
  78. static long bytes;
  79. static struct timeb start_time;
  80.  
  81. static char command[BUFSIZ];
  82.  
  83. static boolean spool = FALSE; /* Received file is into spool dir     */
  84. static char spolname[FILENAME_MAX];
  85.                               /* Final host name of file to be
  86.                                  received into spool directory       */
  87. static char tempname[FILENAME_MAX];
  88.                               /* Temp name used to create received
  89.                                  file                                */
  90.  
  91.  
  92. currentfile();
  93.  
  94. /*--------------------------------------------------------------------*/
  95. /*                    Internal function prototypes                    */
  96. /*--------------------------------------------------------------------*/
  97.  
  98. static boolean pktgetstr( char *s);
  99. static boolean pktsendstr( char *s );
  100.  
  101. static int  bufill(char  *buffer);
  102. static int  bufwrite(char  *buffer,int  len);
  103.  
  104. /*************** SEND PROTOCOL ***************************/
  105.  
  106. /*--------------------------------------------------------------------*/
  107. /*    s d a t a                                                       */
  108. /*                                                                    */
  109. /*    Send File Data                                                  */
  110. /*--------------------------------------------------------------------*/
  111.  
  112. XFER_STATE sdata( void )
  113. {
  114.  
  115.    if ((*sendpkt)((char *) spacket, S_size) != OK) /* send data */
  116.       return XFER_LOST;    /* Trouble!                               */
  117.  
  118.    if ((S_size = bufill((char *) spacket)) == 0)  /* get data from file */
  119.       return XFER_SENDEOF; /* if EOF set state to that               */
  120.  
  121.    return XFER_SENDDATA;   /* Remain in send state                   */
  122. } /*sdata*/
  123.  
  124.  
  125. /*--------------------------------------------------------------------*/
  126. /*    b u f i l l                                                     */
  127. /*                                                                    */
  128. /*    Get a bufferful of data from the file that's being sent.        */
  129. /*    (Should perform input buffering here, perhaps 4K at a time.)    */
  130. /*--------------------------------------------------------------------*/
  131.  
  132. static int bufill(char *buffer)
  133. {
  134.    size_t count = fread(buffer, sizeof *buffer, pktsize, xfer_stream);
  135.  
  136.    bytes += count;
  137.    if ((count < pktsize) && ferror(xfer_stream))
  138.    {
  139.       printerr("bufill");
  140.       clearerr(xfer_stream);
  141.       return -1;
  142.    }
  143.    return count;
  144.  
  145. } /*bufill*/
  146.  
  147. /*--------------------------------------------------------------------*/
  148. /*    b u f w r i t e                                                 */
  149. /*                                                                    */
  150. /*    Write a bufferful of data to the file that's being received.    */
  151. /*--------------------------------------------------------------------*/
  152.  
  153. static int bufwrite(char *buffer, int len)
  154. {
  155.    int count = fwrite(buffer, sizeof *buffer, len, xfer_stream);
  156.  
  157.    bytes += count;
  158.    if (count < len)
  159.    {
  160.       printerr("bufwrite");
  161.       clearerr(xfer_stream);
  162.    }
  163.  
  164.    return count;
  165.  
  166. } /*bufwrite*/
  167.  
  168. /*--------------------------------------------------------------------*/
  169. /*    s b r e a k                                                     */
  170. /*                                                                    */
  171. /*    Switch from master to slave mode                                */
  172. /*                                                                    */
  173. /*    Sequence:                                                       */
  174. /*                                                                    */
  175. /*       We send "H" to other host to ask if we should hang up        */
  176. /*       If it responds "HN", it has work for us, we become           */
  177. /*          the slave.                                                */
  178. /*       If it responds "HY", it has no work for us, we               */
  179. /*          response "HY" (we have no work either), and               */
  180. /*          terminate protocol and hangup                             */
  181. /*                                                                    */
  182. /*    Note that if more work is queued on the local system while      */
  183. /*    we are in slave mode, schkdir() causes us to become the         */
  184. /*    master again; we just decline here to avoid trying the queue    */
  185. /*    again without intervening work from the other side.             */
  186. /*--------------------------------------------------------------------*/
  187.  
  188. XFER_STATE sbreak( void )
  189. {
  190.    if (!pktsendstr("H"))      /* Tell slave it can become the master */
  191.       return XFER_LOST;       /* Xmit fail?  If so, quit transmitting*/
  192.  
  193.    if (!pktgetstr((char *)spacket)) /* Get their response            */
  194.       return XFER_LOST;       /* Xmit fail?  If so, quit transmitting*/
  195.  
  196.    if ((*spacket != 'H') || ((spacket[1] != 'N') && (spacket[1] != 'Y')))
  197.    {
  198.       printmsg(0,"Invalid response from remote: %s",spacket);
  199.       return XFER_ABORT;
  200.    }
  201.  
  202.    if (spacket[1] == 'N')     /* "HN" (have work) message from host? */
  203.    {                          /* Yes --> Enter Receive mode          */
  204.       printmsg( 2, "sbreak: Switch into slave mode" );
  205.       return XFER_SLAVE;
  206.    }
  207.    else {                     /* No --> Remote host is done as well  */
  208.       pktsendstr("HY");       /* Tell the host we are done as well   */
  209.       return XFER_ENDP;       /* Terminate the protocol              */
  210.    } /* else */
  211.  
  212. } /*sbreak*/
  213.  
  214. /*--------------------------------------------------------------------*/
  215. /*    s e o f                                                         */
  216. /*                                                                    */
  217. /*    Send End-Of-File                                                */
  218. /*--------------------------------------------------------------------*/
  219.  
  220. XFER_STATE seof( const boolean purge_file )
  221. {
  222.  
  223.    struct tm  *tmx;
  224.    long ticks;
  225.    struct timeb now;
  226.    char hostname[FILENAME_MAX];
  227.  
  228. /*--------------------------------------------------------------------*/
  229. /*    Send end-of-file indication, and perhaps receive a              */
  230. /*    lower-layer ACK/NAK                                             */
  231. /*--------------------------------------------------------------------*/
  232.  
  233.    switch ((*eofpkt)())
  234.    {
  235.       case RETRY:                /* retry */
  236.          printmsg(0, "Remote system asks that the file be resent");
  237.          fseek(xfer_stream, 0L, SEEK_SET);
  238.          bytes = 0;
  239.          S_size = bufill((char *)spacket);
  240.          if ( S_size == -1 )
  241.             return XFER_ABORT;   /* cannot send file */
  242.          (*filepkt)();           /* warmstart file-transfer protocol */
  243.          return XFER_SENDDATA;   /* stay in data phase */
  244.  
  245.       case FAILED:
  246.          fclose(xfer_stream);
  247.          xfer_stream = NULL;
  248.          return XFER_ABORT;      /* cannot send file */
  249.  
  250.       case OK:
  251.          fclose(xfer_stream);
  252.          xfer_stream = NULL;
  253.          break;                  /* sent, proceed */
  254.  
  255.       default:
  256.          fclose(xfer_stream);
  257.          xfer_stream = NULL;
  258.          return XFER_LOST;
  259.    }
  260.  
  261.    if (!pktgetstr((char *)spacket)) /* Receive CY or CN              */
  262.       return XFER_LOST;       /* Bomb the connection if no packet    */
  263.  
  264.    if ((*spacket != 'C') || ((spacket[1] != 'N') && (spacket[1] != 'Y')))
  265.    {
  266.       printmsg(0,"Invalid response from remote: %s",spacket);
  267.       return XFER_ABORT;
  268.    }
  269.  
  270.    if (!equaln((char *) spacket, "CY", 2))
  271.       printmsg(0,"seof: Host was unable to save file after transmission");
  272.  
  273. /*--------------------------------------------------------------------*/
  274. /*                   If local spool file, delete it                   */
  275. /*--------------------------------------------------------------------*/
  276.  
  277.    importpath(hostname, dname, rmtname);
  278.                               /* Local name also used by logging     */
  279.  
  280.    if (purge_file && !equal(dname,"D.0"))
  281.    {
  282.      unlink( hostname );
  283.      printmsg(4,"seof: Deleted file %s (%s)", dname, hostname );
  284.    } /* if (purge_file && !equal(dname,"D.0")) */
  285.  
  286. /*--------------------------------------------------------------------*/
  287. /*                            Update stats                            */
  288. /*--------------------------------------------------------------------*/
  289.  
  290.    remote_stats.fsent++;
  291.    remote_stats.bsent += bytes;
  292.  
  293.    if (bflag[F_SYSLOG] || (debuglevel > 2 ))
  294.    {
  295.       ftime(&now);
  296.       ticks = (now.time - start_time.time) * 1000 +
  297.                ((long) now.millitm - (long) start_time.millitm);
  298.       printmsg(2, "Transfer completed, %ld chars/sec",
  299.                   (long) ((bytes * 1000) / (ticks ? ticks : 1) ));
  300.  
  301.       if (bflag[F_SYSLOG])
  302.       {
  303.          tmx = localtime(&now.time);
  304.          fprintf( syslog,
  305.                "%s!%s (%s) (%d/%d-%02d:%02d:%02d) -> %ld / %ld.%02d secs\n",
  306.                    nodename, tname, hostname,
  307.                    (tmx->tm_mon+1), tmx->tm_mday,
  308.                    tmx->tm_hour, tmx->tm_min, tmx->tm_sec, bytes,
  309.                    ticks / 1000 , (int) ((ticks % 1000) / 10) );
  310.       } /* if (bflag[F_SYSLOG] ) */
  311.  
  312.    } /* if (bflag[F_SYSLOG] || (debuglevel > 2 )) */
  313.  
  314. /*--------------------------------------------------------------------*/
  315. /*                          Return to caller                          */
  316. /*--------------------------------------------------------------------*/
  317.  
  318.    return XFER_FILEDONE;    /* go get the next file to send */
  319.  
  320. } /*seof*/
  321.  
  322. /*--------------------------------------------------------------------*/
  323. /*    n e w r e q u e s t                                             */
  324. /*                                                                    */
  325. /*    Determine the next request to be sent to other host             */
  326. /*--------------------------------------------------------------------*/
  327.  
  328. XFER_STATE newrequest( void )
  329. {
  330.    int i;
  331.  
  332. /*--------------------------------------------------------------------*/
  333. /*                 Verify we have no work in progress                 */
  334. /*--------------------------------------------------------------------*/
  335.  
  336.    if (!(xfer_stream == NULL))
  337.       return XFER_ABORT;      /* Something's already open.  We're in
  338.                                  trouble!                            */
  339.  
  340.    printmsg(3, "newrequest: looking in work file...");
  341.  
  342. /*--------------------------------------------------------------------*/
  343. /*    Look for work in the current call file; if we do not find       */
  344. /*    any, the job is complete and we can delete all the files we     */
  345. /*    worked on in the file                                           */
  346. /*--------------------------------------------------------------------*/
  347.  
  348.    if (fgets(command, BUFSIZ, fwork) == nil(char))    /* More data?     */
  349.    {                          /* No --> clean up list of files       */
  350.       fclose(fwork);
  351.       fwork = nil(FILE);
  352.       unlink(workfile);       /* Delete completed call file          */
  353.       return XFER_NEXTJOB;    /* Get next C.* file to process     */
  354.    } /* if (fgets(command, BUFSIZ, fwork) == nil(char)) */
  355.  
  356. /*--------------------------------------------------------------------*/
  357. /*                  We have a new request to process                  */
  358. /*--------------------------------------------------------------------*/
  359.  
  360.    i = strlen(command) - 1;
  361.    if (command[i] == '\n')            /* remove new_line from card */
  362.       command[i] = '\0';
  363.  
  364.    sscanf(command, "%c %s %s %s %s %s",
  365.          &type, fname, tname, who, cmdopts, dname);
  366.  
  367. /*--------------------------------------------------------------------*/
  368. /*                           Reset counters                           */
  369. /*--------------------------------------------------------------------*/
  370.  
  371.    bytes = 0;
  372.    ftime(&start_time);
  373.    (*filepkt)();              /* Init for file transfer */
  374.  
  375. /*--------------------------------------------------------------------*/
  376. /*             Process the command according to its type              */
  377. /*--------------------------------------------------------------------*/
  378.  
  379.    switch( type )
  380.    {
  381.       case 'R':
  382.          return XFER_GETFILE;
  383.  
  384.       case 'S':
  385.          return XFER_PUTFILE;
  386.  
  387.       default:
  388.          return XFER_FILEDONE;   /* Ignore the line                  */
  389.    } /* switch */
  390.  
  391. } /* newrequest */
  392.  
  393. /*--------------------------------------------------------------------*/
  394. /*    s s f i l e                                                     */
  395. /*                                                                    */
  396. /*    Send File Header for file to be sent                            */
  397. /*--------------------------------------------------------------------*/
  398.  
  399. XFER_STATE ssfile( void )
  400. {
  401.    char hostfile[FILENAME_MAX];
  402.    char *filename;
  403.  
  404.    if (equal(dname, "D.0"))   /* Is there a spool file?              */
  405.       filename = fname;       /* No --> Use the real name            */
  406.    else
  407.       filename = dname;       /* Yes --> Use it                      */
  408.  
  409. /*--------------------------------------------------------------------*/
  410. /*              Convert the file name to our local name               */
  411. /*--------------------------------------------------------------------*/
  412.  
  413.    importpath(hostfile, filename, rmtname);
  414.  
  415.    printmsg(3, "Opening %s (%s) for sending.", filename, hostfile);
  416.  
  417. /*--------------------------------------------------------------------*/
  418. /*    Try to open the file; if we fail, we just continue, because we  */
  419. /*    may have sent the file on a previous call which failed part     */
  420. /*    way through this job                                            */
  421. /*--------------------------------------------------------------------*/
  422.  
  423.    xfer_stream = FOPEN( hostfile, "r", BINARY );
  424.                                     /* Open stream to send           */
  425.    if (xfer_stream == NULL)
  426.    {
  427.       printmsg(0, "ssfile: Cannot open file %s (%s).", filename, hostfile);
  428.       printerr(hostfile);
  429.       return XFER_FILEDONE;      /* Try next file in this job  */
  430.    } /* if */
  431.  
  432. /*--------------------------------------------------------------------*/
  433. /*              The file is open, now set its buffering               */
  434. /*--------------------------------------------------------------------*/
  435.  
  436.    if (setvbuf( xfer_stream, NULL, _IOFBF, xfer_bufsize))
  437.    {
  438.       printmsg(0, "ssfile: Cannot buffer file %s (%s).", filename, hostfile);
  439.       printerr(hostfile);
  440.       fclose(xfer_stream);
  441.       return XFER_ABORT;         /* Clearly not our day; quit  */
  442.    } /* if */
  443.  
  444. /*--------------------------------------------------------------------*/
  445. /*    Okay, we have a file to process; offer it to the other host     */
  446. /*--------------------------------------------------------------------*/
  447.  
  448.    printmsg(0, "Sending \"%s\" (%s) as \"%s\"", fname, hostfile, tname);
  449.    if (!pktsendstr( command ))   /* Tell them what is coming at them */
  450.       return XFER_LOST;
  451.  
  452.    if (!pktgetstr((char *)spacket))
  453.       return XFER_LOST;
  454.  
  455.    if ((*spacket != 'S') || ((spacket[1] != 'N') && (spacket[1] != 'Y')))
  456.    {
  457.       printmsg(0,"Invalid response from remote: %s",spacket);
  458.       return XFER_ABORT;
  459.    }
  460.  
  461.    if (spacket[1] != 'Y')     /* Otherwise reject file transfer?     */
  462.    {                          /* Yes --> Look for next file          */
  463.       printmsg(0, "ssfile: Remote host rejected file %s, reason %s",
  464.        tname, spacket[2] ? &spacket[2] : "unknown" );
  465.       fclose( xfer_stream );
  466.       xfer_stream = NULL;
  467.       return XFER_FILEDONE;
  468.    }
  469.  
  470.    S_size = bufill((char *) spacket);
  471.    if ( S_size == -1 )
  472.       return XFER_ABORT;   /* cannot send file */
  473.  
  474.    return XFER_SENDDATA;      /* Enter data transmission mode        */
  475.  
  476. } /*ssfile*/
  477.  
  478. /*--------------------------------------------------------------------*/
  479. /*    s r f i l e                                                     */
  480. /*                                                                    */
  481. /*    Send File Header for file to be received                        */
  482. /*--------------------------------------------------------------------*/
  483.  
  484. XFER_STATE srfile( void )
  485. {
  486.    char hostfile[FILENAME_MAX];
  487.    struct  stat    statbuf;
  488.  
  489. /*--------------------------------------------------------------------*/
  490. /*               Convert the filename to our local name               */
  491. /*--------------------------------------------------------------------*/
  492.  
  493.    importpath(hostfile, tname, rmtname);
  494.  
  495. /*--------------------------------------------------------------------*/
  496. /*    If the destination is a directory, put the originating          */
  497. /*    original file name at the end of the path                       */
  498. /*--------------------------------------------------------------------*/
  499.  
  500.    if ((hostfile[strlen(hostfile) - 1] == '/') ||
  501.        ((stat(hostfile , &statbuf) == 0) && (statbuf.st_mode & S_IFDIR)))
  502.    {
  503.       char *slash = strrchr( fname, '/');
  504.  
  505.       if ( slash == NULL )
  506.          slash = fname;
  507.       else
  508.          slash ++ ;
  509.  
  510.       printmsg(3, "srfile: Destination \"%s\" is directory, \
  511. appending filename \"%s\"", hostfile, slash);
  512.  
  513.       if (hostfile[strlen(hostfile) - 1] != '/')
  514.          strcat(hostfile, "/");
  515.  
  516.       strcat( hostfile, slash );
  517.    } /* if */
  518.  
  519.    printmsg(0, "Receiving \"%s\" as \"%s\" (%s)", fname, tname, hostfile);
  520.  
  521.    if (!pktsendstr( command ))
  522.       return XFER_LOST;
  523.  
  524.    if (!pktgetstr((char *)spacket))
  525.       return XFER_LOST;
  526.  
  527.    if ((*spacket != 'R') || ((spacket[1] != 'N') && (spacket[1] != 'Y')))
  528.    {
  529.       printmsg(0,"Invalid response from remote: %s",spacket);
  530.       return XFER_ABORT;
  531.    }
  532.  
  533.    if (spacket[1] != 'Y')     /* Otherwise reject file transfer?     */
  534.    {                          /* Yes --> Look for next file          */
  535.       printmsg(0, "srfile: Remote host denied access to file %s, reason %s",
  536.          fname, spacket[2] ? &spacket[2] : "unknown" );
  537.       fclose( xfer_stream );
  538.       xfer_stream = NULL;
  539.       return XFER_FILEDONE;
  540.    }
  541.  
  542. /*--------------------------------------------------------------------*/
  543. /*    We should verify the directory exists if the user doesn't       */
  544. /*    specify the -d option, but I've got enough problems this        */
  545. /*    week; we'll just auto-create using FOPEN()                      */
  546. /*--------------------------------------------------------------------*/
  547.  
  548.    xfer_stream = FOPEN(hostfile, "w", BINARY);
  549.                            /* Allow auto-create of directory      */
  550.    if (xfer_stream == NULL)
  551.    {
  552.       printmsg(0, "srfile: cannot create %s", hostfile);
  553.       printerr(hostfile);
  554.       return XFER_ABORT;
  555.    }
  556.  
  557. /*--------------------------------------------------------------------*/
  558. /*                     Set buffering for the file                     */
  559. /*--------------------------------------------------------------------*/
  560.  
  561.    if (setvbuf( xfer_stream, NULL, _IOFBF, xfer_bufsize))
  562.    {
  563.       printmsg(0, "srfile: Cannot buffer file %s (%s).",
  564.           tname, hostfile);
  565.       printerr(hostfile);
  566.       fclose(xfer_stream);
  567.       return XFER_ABORT;
  568.    } /* if */
  569.  
  570.    spool = FALSE;             /* Do not rename file at completion */
  571.    return XFER_RECVDATA;      /* Now start receiving the data     */
  572.  
  573. } /*stfile*/
  574.  
  575. /*--------------------------------------------------------------------*/
  576. /*    s i n i t                                                       */
  577. /*                                                                    */
  578. /*    Send Initiate:  send this host's parameters and get other       */
  579. /*    side's back.                                                    */
  580. /*--------------------------------------------------------------------*/
  581.  
  582. XFER_STATE sinit( void )
  583. {
  584.  
  585.    return (*openpk)() ? XFER_ABORT : XFER_MASTER;
  586.  
  587. } /*sinit*/
  588.  
  589.  
  590. /*********************** MISC SUB SUB PROTOCOL *************************/
  591.  
  592. /*
  593.    s c h k d i r
  594.  
  595.    scan spooling directory for C.* files for the other system
  596. */
  597.  
  598. XFER_STATE schkdir( const boolean outbound )
  599. {
  600.    XFER_STATE c;
  601.  
  602.    if ( hostp->hsecure->sendfiles || outbound )
  603.                                  /* Send our work to other host?        */
  604.    {
  605.       c = scandir(rmtname);      /* Determine if data for the host      */
  606.       scandir( NULL );           /* Reset directory search pointers     */
  607.    }
  608.    else
  609.       c = XFER_NOLOCAL;       /* Do not send data on inbound call    */
  610.  
  611.    switch ( c )
  612.    {
  613.       case XFER_ABORT:        /* Internal error opening file         */
  614.          return XFER_ABORT;
  615.  
  616.       case XFER_NOLOCAL:      /* No work for host                    */
  617.          if (! pktsendstr("HY") )
  618.             return XFER_LOST;
  619.  
  620.          if (!pktgetstr((char *)rpacket))
  621.             return XFER_LOST; /* Didn't get response, die quietly    */
  622.          else
  623.             return XFER_ENDP; /* Got response, we're out of here     */
  624.  
  625.       case XFER_REQUEST:
  626.          if (! pktsendstr("HN") )
  627.             return XFER_LOST;
  628.          else {
  629.             printmsg( 2, "schkdir: Switch into master mode" );
  630.             return XFER_MASTER;
  631.          }
  632.  
  633.       default:
  634.          panic();
  635.          return XFER_ABORT;
  636.  
  637.    } /* switch */
  638. } /*schkdir*/
  639.  
  640. /*--------------------------------------------------------------------*/
  641. /*    e n d p                                                         */
  642. /*                                                                    */
  643. /*    end the protocol                                                */
  644. /*--------------------------------------------------------------------*/
  645.  
  646. XFER_STATE endp( void )
  647. {
  648.    (*closepk)();
  649.  
  650.    if (spool)
  651.    {
  652.       unlink(tempname);
  653.       spool = FALSE;
  654.    }
  655.    return XFER_EXIT;
  656.  
  657. } /*endp*/
  658.  
  659.  
  660. /*********************** RECIEVE PROTOCOL **********************/
  661.  
  662. /*--------------------------------------------------------------------*/
  663. /*    r i n i t                                                       */
  664. /*                                                                    */
  665. /*    Receive Initialization                                          */
  666. /*--------------------------------------------------------------------*/
  667.  
  668. XFER_STATE rinit( void )
  669. {
  670.  
  671.    return (*openpk)() == OK  ? XFER_SLAVE : XFER_LOST;
  672.  
  673. } /*rinit*/
  674.  
  675. /*--------------------------------------------------------------------*/
  676. /*    r h e a d e r                                                   */
  677. /*                                                                    */
  678. /*    Receive File Header                                             */
  679. /*--------------------------------------------------------------------*/
  680.  
  681. XFER_STATE rheader( void )
  682. {
  683.    if (!pktgetstr(command))
  684.       return XFER_LOST;
  685.  
  686. /*--------------------------------------------------------------------*/
  687. /*        Return if the remote system has no more data for us         */
  688. /*--------------------------------------------------------------------*/
  689.  
  690.    if ((command[0] & 0x7f) == 'H')
  691.       return XFER_NOREMOTE;   /* Report master has no more data to   */
  692.  
  693. /*--------------------------------------------------------------------*/
  694. /*                  Begin transforming the file name                  */
  695. /*--------------------------------------------------------------------*/
  696.  
  697.    printmsg(3, "rfile: command \"%s\"", command);
  698.  
  699.    sscanf(command, "%c %s %s %s %s %s",
  700.          &type, fname, tname, who, cmdopts, dname);
  701.  
  702. /*--------------------------------------------------------------------*/
  703. /*                           Reset counters                           */
  704. /*--------------------------------------------------------------------*/
  705.  
  706.    ftime(&start_time);
  707.    bytes = 0;
  708.    (*filepkt)();              /* Init for file transfer */
  709.  
  710. /*--------------------------------------------------------------------*/
  711. /*                 Return with next state to process                  */
  712. /*--------------------------------------------------------------------*/
  713.  
  714.    switch (type)
  715.    {
  716.       case 'R':
  717.          return XFER_GIVEFILE;
  718.  
  719.       case 'S':
  720.          return XFER_TAKEFILE;
  721.  
  722.       default:
  723.          printmsg(0,"rheader: Unsupported verb \"%c\" rejected",type);
  724.          if (!pktsendstr("XN"))  /* Reject the request               */
  725.             return XFER_LOST;    /* Die if reponse fails             */
  726.          else
  727.             return XFER_FILEDONE;   /* Process next request          */
  728.    } /* switch */
  729.  
  730. } /* rheader */
  731.  
  732. /*--------------------------------------------------------------------*/
  733. /*    r r f i l e                                                     */
  734. /*                                                                    */
  735. /*    Setup for receiving a file as requested by the remote host      */
  736. /*--------------------------------------------------------------------*/
  737.  
  738. XFER_STATE rrfile( void )
  739. {
  740.    char filename[FILENAME_MAX];
  741.    size_t subscript;
  742.    struct  stat    statbuf;
  743.  
  744. /*--------------------------------------------------------------------*/
  745. /*       Determine if the file can go into the spool directory        */
  746. /*--------------------------------------------------------------------*/
  747.  
  748.    spool = ((*tname == 'D') || (*tname == 'X')) && tname[1] == '.';
  749.  
  750.    expand_path( strcpy( filename, tname),
  751.       spool ? "." : securep->pubdir, securep->pubdir , NULL );
  752.  
  753.    printmsg(3, "rrfile: destination \"%s\"", filename );
  754.  
  755. /*--------------------------------------------------------------------*/
  756. /*       Check if the name is a directory name (end with a '/')       */
  757. /*--------------------------------------------------------------------*/
  758.  
  759.    subscript = strlen( filename ) - 1;
  760.  
  761.    if ((filename[subscript] == '/') ||
  762.        ((stat(filename , &statbuf) == 0) && (statbuf.st_mode & S_IFDIR)))
  763.    {
  764.       char *slash = strrchr(fname, '/');
  765.       if (slash  == NULL)
  766.          slash = fname;
  767.       else
  768.          slash++;
  769.  
  770.       printmsg(3, "rrfile: destination is directory \"%s\", adding \"%s\"",
  771.                filename, slash);
  772.  
  773.       if ( filename[ subscript ] != '/')
  774.          strcat(filename, "/");
  775.       strcat(filename, slash);
  776.    } /* if */
  777.  
  778. /*--------------------------------------------------------------------*/
  779. /*          Let host munge filename as appropriate                    */
  780. /*--------------------------------------------------------------------*/
  781.  
  782.    importpath(spolname, filename, rmtname);
  783.  
  784. /*--------------------------------------------------------------------*/
  785. /* If the name has a path and we don't allow it, reject the transfer  */
  786. /*--------------------------------------------------------------------*/
  787.  
  788.    if ( !spool && !ValidateFile( spolname , ALLOW_WRITE ))
  789.    {
  790.       if (!pktsendstr("SN2")) /* Report access denied to requestor   */
  791.          return XFER_LOST;
  792.       else
  793.          return XFER_FILEDONE;   /* Look for next file from master   */
  794.    } /* if */
  795.  
  796. /*--------------------------------------------------------------------*/
  797. /*            The filename is transformed, try to open it             */
  798. /*--------------------------------------------------------------------*/
  799.  
  800.    if (spool)
  801.       xfer_stream = fopen( tmpnam( tempname ), "wb");
  802.    else if (strchr( cmdopts,'d'))
  803.       xfer_stream = FOPEN( spolname, "w", BINARY );
  804.    else
  805.       xfer_stream = fopen( spolname, "wb");
  806.  
  807.  
  808.    if (xfer_stream == NULL)
  809.    {
  810.       printmsg(0, "rrfile: cannot open file %s (%s).",
  811.            filename, spool ? tempname : spolname);
  812.       printerr(spool ? tempname : spolname);
  813.       if (!pktsendstr("SN4"))    /* Report cannot create file     */
  814.          return XFER_LOST;       /* School is out, die            */
  815.       else
  816.          return XFER_FILEDONE;   /* Tell them to send next file   */
  817.    } /* if */
  818.  
  819. /*--------------------------------------------------------------------*/
  820. /*               The file is open, now try to buffer it               */
  821. /*--------------------------------------------------------------------*/
  822.  
  823.    if (setvbuf( xfer_stream, NULL, _IOFBF, xfer_bufsize))
  824.    {
  825.       printmsg(0, "rrfile: cannot buffer file %s (%s).",
  826.           filename, spool ? tempname : spolname);
  827.       printerr(spool ? tempname : spolname);
  828.       fclose(xfer_stream);
  829.       pktsendstr("SN4");             /* Report cannot create file     */
  830.       return XFER_ABORT;
  831.    } /* if */
  832.  
  833. /*--------------------------------------------------------------------*/
  834. /*    Announce we are receiving the file to console and to remote     */
  835. /*--------------------------------------------------------------------*/
  836.  
  837.    printmsg(0, "Receiving \"%s\" as \"%s\" (%s)",
  838.                fname,filename,spolname);
  839.    printmsg(2,"Using temp name %s",tempname);
  840.  
  841.    if (!pktsendstr("SY"))
  842.       return XFER_LOST;
  843.  
  844.    return XFER_RECVDATA;   /* Switch to data state                */
  845.  
  846. } /*rrfile*/
  847.  
  848. /*--------------------------------------------------------------------*/
  849. /*    r s f i l e                                                     */
  850. /*                                                                    */
  851. /*    Receive File Header for a file remote has requested us to       */
  852. /*    send                                                            */
  853. /*--------------------------------------------------------------------*/
  854.  
  855. XFER_STATE rsfile( void )
  856. {
  857.    char filename[FILENAME_MAX];
  858.    char hostname[FILENAME_MAX];
  859.    struct  stat    statbuf;
  860.    size_t subscript;
  861.  
  862.    expand_path( strcpy(filename, fname ) ,
  863.                 securep->pubdir ,
  864.                 securep->pubdir ,
  865.                 NULL );
  866.  
  867. /*--------------------------------------------------------------------*/
  868. /*               Let host munge filename as appropriate               */
  869. /*--------------------------------------------------------------------*/
  870.  
  871.    importpath(hostname, filename, rmtname);
  872.    printmsg(3, "rsfile: input \"%s\", source \"%s\", host \"%s\"",
  873.                                     fname, filename , hostname);
  874.  
  875. /*--------------------------------------------------------------------*/
  876. /*       Check if the name is a directory name (end with a '/')       */
  877. /*--------------------------------------------------------------------*/
  878.  
  879.    subscript = strlen( filename ) - 1;
  880.  
  881.    if ((filename[subscript] == '/') ||
  882.        ((stat(hostname , &statbuf) == 0) && (statbuf.st_mode & S_IFDIR)))
  883.    {
  884.       printmsg(3, "rsfile: source is directory \"%s\", rejecting",
  885.                hostname);
  886.  
  887.       if (!pktsendstr("RN2"))    /* Report cannot send file       */
  888.          return XFER_LOST;       /* School is out, die            */
  889.       else
  890.          return XFER_FILEDONE;   /* Tell them to send next file   */
  891.    } /* if */
  892.  
  893. /*--------------------------------------------------------------------*/
  894. /*                Check the access to the file desired                */
  895. /*--------------------------------------------------------------------*/
  896.  
  897.    if ( !ValidateFile( hostname , ALLOW_READ ))
  898.    {
  899.       if (!pktsendstr("RN2")) /* Report access denied to requestor   */
  900.          return XFER_LOST;
  901.       else
  902.          return XFER_FILEDONE;   /* Look for next file from master   */
  903.    } /* if */
  904.  
  905. /*--------------------------------------------------------------------*/
  906. /*            The filename is transformed, try to open it             */
  907. /*--------------------------------------------------------------------*/
  908.  
  909.    printmsg(3, "Opening %s (%s) for sending.", fname, hostname);
  910.    xfer_stream = FOPEN( hostname, "r" , BINARY);
  911.                               /* Open stream to transmit       */
  912.    if (xfer_stream == NULL)
  913.    {
  914.       printmsg(0, "rsfile: Cannot open file %s (%s).", fname, hostname);
  915.       printerr(hostname);
  916.       if (!pktsendstr("RN2"))    /* Report cannot send file       */
  917.          return XFER_LOST;       /* School is out, die            */
  918.       else
  919.          return XFER_FILEDONE;   /* Tell them to send next file   */
  920.    } /* if */
  921.  
  922.    if (setvbuf( xfer_stream, NULL, _IOFBF, xfer_bufsize))
  923.    {
  924.       printmsg(0, "rsfile: Cannot buffer file %s (%s).", fname, hostname);
  925.       pktsendstr("RN2");         /* Tell them we cannot handle it */
  926.       printerr(hostname);
  927.       fclose(xfer_stream);
  928.       return XFER_ABORT;
  929.    } /* if */
  930.  
  931. /*--------------------------------------------------------------------*/
  932. /*  We have the file open, announce it to the log and to the remote   */
  933. /*--------------------------------------------------------------------*/
  934.  
  935.    if (!pktsendstr("RY"))
  936.       return XFER_LOST;
  937.  
  938.    printmsg(0, "Sending \"%s\" (%s) as \"%s\"", fname, hostname, tname);
  939.    S_size = bufill((char *) spacket);
  940.    if ( S_size == -1 )
  941.       return XFER_ABORT;   /* cannot send file */
  942.  
  943.    return XFER_SENDDATA;   /* Switch to send data state        */
  944.  
  945. } /*rsfile*/
  946.  
  947. /*--------------------------------------------------------------------*/
  948. /*    r d a t a                                                       */
  949. /*                                                                    */
  950. /*    Receive Data                                                    */
  951. /*--------------------------------------------------------------------*/
  952.  
  953. XFER_STATE rdata( void )
  954. {
  955.    int   len;
  956.  
  957.    if ((*getpkt)((char *) rpacket, &len) != OK)
  958.       return XFER_LOST;
  959.  
  960. /*--------------------------------------------------------------------*/
  961. /*                         Handle end of file                         */
  962. /*--------------------------------------------------------------------*/
  963.  
  964.    if (len == 0)
  965.       return XFER_RECVEOF;
  966.  
  967. /*--------------------------------------------------------------------*/
  968. /*                  Write incoming data to the file                   */
  969. /*--------------------------------------------------------------------*/
  970.  
  971.    if (bufwrite((char *) rpacket, len) < len) {                   /* ahd   */
  972.       printmsg(0, "rdata: Error writing data to file.");
  973.       return XFER_ABORT;
  974.    }
  975.  
  976.    return XFER_RECVDATA;      /* Remain in data state                */
  977.  
  978. } /*rdata*/
  979.  
  980. /*--------------------------------------------------------------------*/
  981. /*    r e o f                                                         */
  982. /*                                                                    */
  983. /*    Process EOF for a received file                                 */
  984. /*--------------------------------------------------------------------*/
  985.  
  986. XFER_STATE reof( void )
  987. {
  988.    struct tm *tmx;
  989.    struct timeb now;
  990.    long ticks;
  991.    char *cy = "CY";
  992.    char *cn = "CN";
  993.    char *response = cy;
  994.    char *fname = spool ? tempname : spolname;
  995.  
  996. /*--------------------------------------------------------------------*/
  997. /*            Close out the file, checking for I/O errors             */
  998. /*--------------------------------------------------------------------*/
  999.  
  1000.    fclose(xfer_stream);
  1001.    if (ferror (xfer_stream ))
  1002.    {
  1003.       response = cn;          /* Report we had a problem             */
  1004.       printerr( fname );
  1005.    }
  1006.  
  1007.    xfer_stream = NULL;        /* To make sure!                       */
  1008.  
  1009. /*--------------------------------------------------------------------*/
  1010. /*    If it was a spool file, rename it to its permanent location     */
  1011. /*--------------------------------------------------------------------*/
  1012.  
  1013.    if (spool && equal(response,cy))
  1014.    {
  1015.       unlink( spolname );     /* Should be safe, since we only do it
  1016.                                  for spool files                     */
  1017.  
  1018.       if ( RENAME(tempname, spolname ))
  1019.       {
  1020.          printmsg(0,"reof: Unable to rename %s to %s",
  1021.                   tempname, spolname);
  1022.          response = cn;
  1023.          printerr(spolname);
  1024.       } /* if ( RENAME(tempname, spolname )) */
  1025.       spool = FALSE;
  1026.    } /* if (equal(response,cy) && spool) */
  1027.  
  1028.    if (!pktsendstr(response)) /* Announce we accepted the file       */
  1029.       return XFER_LOST;       /* No ACK?  Return, if so              */
  1030.  
  1031.    if ( !equal(response, cy) )   /* If we had an error, delete file  */
  1032.    {
  1033.       printmsg(0,"reof: Deleting corrupted file %s", fname );
  1034.       unlink(fname );
  1035.       return XFER_ABORT;
  1036.    } /* if ( !equal(response, cy) ) */
  1037.  
  1038. /*--------------------------------------------------------------------*/
  1039. /*            The file is delivered; compute stats for it             */
  1040. /*--------------------------------------------------------------------*/
  1041.  
  1042.    remote_stats.freceived++;
  1043.    remote_stats.breceived += bytes;
  1044.  
  1045.    if (bflag[F_SYSLOG] || (debuglevel > 2 ))
  1046.    {
  1047.       ftime(&now);
  1048.       ticks = (now.time - start_time.time) * 1000 +
  1049.                ((long) now.millitm - (long) start_time.millitm);
  1050.       printmsg(2, "Transfer completed, %ld chars/sec",
  1051.                   (long) ((bytes * 1000) / (ticks ? ticks : 1) ));
  1052.  
  1053.       if ( bflag[F_SYSLOG] )
  1054.       {
  1055.          tmx = localtime(&now.time);
  1056.          fprintf( syslog,
  1057.             "%s!%s (%s) (%d/%d-%02d:%02d:%02d) <- %ld / %ld.%02d secs\n",
  1058.                    rmtname, tname, spolname,
  1059.                    (tmx->tm_mon+1), tmx->tm_mday,
  1060.                    tmx->tm_hour, tmx->tm_min, tmx->tm_sec, bytes,
  1061.                    ticks / 1000 , (int) ((ticks % 1000) / 10) );
  1062.       } /* if ( bflag[SYSLOG ) */
  1063.    } /* if (bflag[F_SYSLOG] || (debuglevel > 2 )) */
  1064.  
  1065. /*--------------------------------------------------------------------*/
  1066. /*                      Return success to caller                      */
  1067. /*--------------------------------------------------------------------*/
  1068.  
  1069.    return XFER_FILEDONE;
  1070. } /* reof */
  1071.  
  1072. /*--------------------------------------------------------------------*/
  1073. /*                           MISC ROUTINES                            */
  1074. /*--------------------------------------------------------------------*/
  1075.  
  1076. /*--------------------------------------------------------------------*/
  1077. /*    p k t s e n d s t r                                             */
  1078. /*                                                                    */
  1079. /*    Transmit a control packet                                       */
  1080. /*--------------------------------------------------------------------*/
  1081.  
  1082. static boolean pktsendstr( char *s )
  1083. {
  1084.    printmsg(2, ">>> %s", s);
  1085.  
  1086.    if((*wrmsg)(s) != OK )
  1087.       return FALSE;
  1088.  
  1089.    remote_stats.bsent += strlen(s)+1;
  1090.  
  1091.    return TRUE;
  1092. } /* pktsendstr */
  1093.  
  1094. /*--------------------------------------------------------------------*/
  1095. /*    p k t g e t s t r                                               */
  1096. /*                                                                    */
  1097. /*    Receive a control packet                                        */
  1098. /*--------------------------------------------------------------------*/
  1099.  
  1100. static boolean pktgetstr( char *s)
  1101. {
  1102.    if ((*rdmsg)(s) != OK )
  1103.      return FALSE;
  1104.  
  1105.    remote_stats.breceived += strlen( s ) + 1;
  1106.    printmsg(2, "<<< %s", s);
  1107.  
  1108.    return TRUE;
  1109. } /* pktgetstr */
  1110.